﻿#include "FrameFIFOBuf.h"
#ifndef _WIN32
#include <fcntl.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#endif // _WIN32

CReplayFrmBuf::CReplayFrmBuf()
{
	m_frameNO = 0;
	m_pFrm = NULL;
	m_nextFrmTm = 0;
}

CReplayFrmBuf::~CReplayFrmBuf()
{

}

int CReplayFrmBuf::Open(int ch, int bufSize)
{
	int destBufSize = bufSize + sizeof(LHN_FRAME_H);
	int ret = open(destBufSize);

	m_buf_size = bufSize;
	m_channel  = ch;
	m_frameNO  = 0;

	return ret;
}

int CReplayFrmBuf::PutFrame(uchar_t * buf, uint32_t frameLen)
{
	//写入数据帧
	int ret = 0;
	int len = 0;
	if(m_buf_size == 0)
	{
		return ERR_DATA_BUF_EMPYT;
	}

	if((len = m_buf_size - m_pidx) < BASE_FRAME_HEAD_LEN)
	{   //镜像视频帧头,由于缓冲大小已经预先多开辟了一个帧头的大小
		memcpy(m_buf + m_pidx ,buf,BASE_FRAME_HEAD_LEN);
	}

	ret = write(buf,frameLen);

	return ret;
}

uint8_t CReplayFrmBuf::GetNextFrameType()
{
	uint32_t dataSize = 0;
	bool bFound = false;
	dataSize = GetDataSize();
	if(dataSize <= BASE_FRAME_HEAD_LEN)
	{
		//保证最少有一个帧头的数据大小
		return 0;
	}
	Lock();
	uint32_t len = m_buf_size - m_cidx;
	uint32_t diffOffset = 0;

	if(len < BASE_FRAME_HEAD_LEN)
	{  //将未的头信息镜像出来
		memcpy(m_buf,m_buf + m_buf_size,BASE_FRAME_HEAD_LEN);
	}

	LHN_FRAME_H   * pFrm = (LHN_FRAME_H * )(m_buf + m_cidx);
	if(LHNFrameTag != pFrm->frameTag)
	{
		diffOffset = 1;
		while (diffOffset+FRAME_H_LEN + m_cidx < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= dataSize)
			{
				break;
			}
			pFrm = (LHN_FRAME_H * )(m_buf + m_cidx + diffOffset);
			if( LHNFrameTag == pFrm->frameTag)
			{
				break;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound)
		{
			ConsumeBuf(diffOffset);
			goto ERR_OUT;
		}
		else
		{
			if(0 != diffOffset)
			{
				ConsumeBuf(diffOffset);
			}
		}
	}

	Unlock();
	return pFrm->frameType;
ERR_OUT:
	Unlock();
	return 0;
}

int CReplayFrmBuf::GetFrame(uchar_t * buf, uint32_t frameLen,bool bPeek)
{
	int ret = 0;
    uint32_t dataSize = 0;
	uint32_t frame_size = 0;
	bool bFound = false;
    dataSize = GetDataSize();
	if(dataSize <= BASE_FRAME_HEAD_LEN)
    {
        //保证最少有一个帧头的数据大小
        return ERR_FIFO_NOTENOUGH;
    }
	Lock();
    uint32_t len = m_buf_size - m_cidx;
	uint32_t diffOffset = 0;

	if(len < BASE_FRAME_HEAD_LEN)
	{  //将未的头信息镜像出来
		memcpy(m_buf + m_buf_size,m_buf,BASE_FRAME_HEAD_LEN);
	}
	LHN_FRAME_H   * pFrm = (LHN_FRAME_H * )(m_buf + m_cidx);

	if(LHNFrameTag != pFrm->frameTag)
	{
		diffOffset = 1;
		while (diffOffset+FRAME_H_LEN + m_cidx < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= dataSize)
			{
				break;
			}
			pFrm = (LHN_FRAME_H * )(m_buf + m_cidx + diffOffset);
			if( LHNFrameTag == pFrm->frameTag)
			{
				break;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound )
		{
			if(len < BASE_FRAME_HEAD_LEN)
			{
				ConsumeBuf(BASE_FRAME_HEAD_LEN);
			}
			else
			{
				ConsumeBuf(diffOffset);
			}

			goto ERR_OUT;
		}
		else
		{
			if(0 != diffOffset)
			{
				ConsumeBuf(diffOffset);
			}
		}
	}

	dataSize = GetDataSize();
	frame_size = pFrm->dataLen + FRAME_H_LEN;
	if( frame_size > dataSize)
	{
		m_lock.UnLock();
		return ERR_DATA_AREA;
	}

	len = m_buf_size - m_cidx;
	if(frame_size > len)
	{
		memcpy(buf, m_buf + m_cidx, len);
		memcpy(buf + len, m_buf, frame_size - len);
	}
	else
	{
		memcpy(buf,m_buf + m_cidx,frame_size);
	}
	m_nextFrmTm = pFrm->pts;
	if(bPeek)
	{
		ConsumeBuf(frame_size);
	}
	
	Unlock();
    return frame_size;
ERR_OUT:
    Unlock();
    return ret;
}

int  CReplayFrmBuf::GetAVIFrame(uchar_t * buf, uint32_t frameLen,bool bPeek)
{
	int ret = 0;
	uint32_t dataSize = 0;
	uint32_t frame_size = 0;
	bool bFound = false;
	dataSize = GetDataSize();
	if(dataSize <= BASE_FRAME_HEAD_LEN)
	{
		//保证最少有一个帧头的数据大小
		return ERR_FIFO_NOTENOUGH;
	}

	Lock();
	uint32_t len = m_buf_size - m_cidx;
	uint32_t diffOffset = 0;

	if(len < 8)
	{  //将未的头信息镜像出来
		memcpy(m_buf + m_buf_size,m_buf,8);
	}

	struct AVI_MOV_BOX
	{
		uint32_t magic;
		uint32_t size ;
	};

	AVI_MOV_BOX * pAviBox = NULL;

	static uint32_t  videoFlag = mmioFOURCC('0','0','d','b');
	
	pAviBox = (AVI_MOV_BOX * )(m_buf + m_cidx);

	if(videoFlag != pAviBox->magic)
	{
		diffOffset = 1;
		while (diffOffset+FRAME_H_LEN + m_cidx < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= dataSize)
			{
				break;
			}
			pAviBox = (AVI_MOV_BOX * )(m_buf + m_cidx + diffOffset);
			if( videoFlag == pAviBox->magic)
			{
				break;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound )
		{
			if(len < BASE_FRAME_HEAD_LEN)
			{
				ConsumeBuf(BASE_FRAME_HEAD_LEN);
			}
			else
			{
				ConsumeBuf(diffOffset);
			}

			goto ERR_OUT;
		}
		else
		{
			if(0 != diffOffset)
			{
				ConsumeBuf(diffOffset);
			}
		}
	}

	dataSize = GetDataSize();
	frame_size = pAviBox->size + 8;
	if( frame_size > dataSize)
	{
		m_lock.UnLock();
		return ERR_DATA_AREA;
	}

	len = m_buf_size - m_cidx;
	if(frame_size > len)
	{
		memcpy(buf, m_buf + m_cidx, len);
		memcpy(buf + len, m_buf, frame_size - len);
	}
	else
	{
		memcpy(buf,m_buf + m_cidx,frame_size);
	}

	if(bPeek)
	{
		ConsumeBuf(frame_size);
	}

	Unlock();
	return frame_size;
ERR_OUT:
	Unlock();
	return ret;
}


int  CReplayFrmBuf::GetFrameNoneHead(uchar_t * buf, uint32_t frameLen)
{
	int ret = 0;
	uint32_t dataSize = 0;
	uint32_t frame_size = 0;
	bool bFound = false;
	dataSize = GetDataSize();
	if(dataSize <= BASE_FRAME_HEAD_LEN)
	{
		//保证最少有一个帧头的数据大小
		return ERR_FIFO_NOTENOUGH;
	}
	Lock();
	uint32_t len = m_buf_size - m_cidx;
	uint32_t diffOffset = 0;

	if(len < BASE_FRAME_HEAD_LEN)
	{  //将未的头信息镜像出来
		memcpy(m_buf + m_buf_size,m_buf,BASE_FRAME_HEAD_LEN);
	}

	LHN_FRAME_H   * pFrm = (LHN_FRAME_H * )(m_buf + m_cidx);

	if(LHNFrameTag != pFrm->frameTag)
	{
		diffOffset = 1;
		while (diffOffset+FRAME_H_LEN + m_cidx < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= dataSize)
			{
				break;
			}
			pFrm = (LHN_FRAME_H * )(m_buf + m_cidx + diffOffset);
			if( LHNFrameTag == pFrm->frameTag)
			{
				break;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound)
		{
			ConsumeBuf(diffOffset);
			goto ERR_OUT;
		}
		else
		{
			if(0 != diffOffset)
			{
				ConsumeBuf(diffOffset);
			}
		}
	}

	dataSize = GetDataSize();
	frame_size = pFrm->dataLen + FRAME_H_LEN;
	if( frame_size > dataSize)
	{
		m_lock.UnLock();
		return ERR_DATA_AREA;
	}

	len = m_buf_size - m_cidx;
	if(frame_size > len)
	{
		if(len > FRAME_H_LEN )
		{
			memcpy(buf, m_buf + m_cidx + FRAME_H_LEN, len - FRAME_H_LEN);
			memcpy(buf + len, m_buf, pFrm->dataLen - (len - FRAME_H_LEN));
		}
		else
		{  // 极少的情况出现
			memcpy(buf + len, m_buf + FRAME_H_LEN - len , pFrm->dataLen);
		}
	}
	else
	{
		memcpy(buf,m_buf + m_cidx ,pFrm->dataLen);
	}

	m_nextFrmTm = pFrm->pts;
	ConsumeBuf(frame_size);
	Unlock();
	return  pFrm->dataLen;
ERR_OUT:
	Unlock();
	return ret;
}
int CReplayFrmBuf::GetNextFrmSize()
{
	return 0;
}

int64_t  CReplayFrmBuf::GetNextFrmTime()
{
	return m_nextFrmTm;
}

int CReplayFrmBuf::GetFrmBuf(FRAME_CRT_ADDR & frmAddr,uint32_t frmHeadSize,uint32_t frmSize)
{

	if (0 == frmSize)
	{
		return ERR_DATA_SIZE;
	}

	m_lock.Lock();
	uint32_t len = m_buf_size - m_pidx;

	if(len < frmSize)
	{
		if(len < frmHeadSize )
		{
			frmAddr.bDeviHead = true;
			frmAddr.pHead     = m_buf + m_pidx;

			frmAddr.pHeadFragment = m_buf;
			frmAddr.fragmentSz = frmHeadSize - len;

			frmAddr.pBody     = m_buf + (frmHeadSize - len);
			frmAddr.bodySize  = frmSize;

			frmAddr.pTail     = NULL;
			frmAddr.tailSize  = 0;
		}
		else
		{
			frmAddr.bDeviHead = false;
			frmAddr.pHead     = m_buf + m_pidx;

			frmAddr.pHeadFragment = NULL;
			frmAddr.fragmentSz = 0;

			frmAddr.pBody     = m_buf + m_pidx + frmHeadSize;
			frmAddr.bodySize  = len - frmHeadSize ;

			frmAddr.pTail     = m_buf;
			frmAddr.tailSize  = frmSize - frmAddr.bodySize;
		}
	}
	else
	{
		frmAddr.bDeviHead = false;
		frmAddr.pHead     = m_buf + m_pidx;

		frmAddr.pHeadFragment = NULL;
		frmAddr.fragmentSz = 0;

		frmAddr.pBody     = m_buf + m_pidx + frmHeadSize;
		frmAddr.bodySize  = len - frmHeadSize;

		frmAddr.pTail     = NULL;
		frmAddr.tailSize  = 0;
	}
	frmAddr.frameSize = frmSize;
	frmAddr.dataPos  =0 ;
	frmAddr.bStart  = true;
	m_lock.UnLock();
	return 0;
}

